package com.sixmac.core.aop;

import com.sixmac.core.annotation.Validator;
import com.sixmac.core.base.model.Format;
import com.sixmac.core.toolbox.ajax.AjaxResult;
import com.sixmac.core.toolbox.kit.HttpKit;
import com.sixmac.core.toolbox.kit.LogKit;
import com.sixmac.core.toolbox.kit.StrKit;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 说明：参数验证
 * Created by tangxh on 2016/11/24.
 */
@Aspect
@Component
public class ValidatorAop {

	@Pointcut(value = "@annotation(com.sixmac.core.annotation.Validator)")
	private void cutBefore() {

	}

	@Around("cutBefore()")
	public Object doValidator(ProceedingJoinPoint point) throws Throwable {
		HttpServletRequest request = HttpKit.getRequest();
		MethodSignature ms = (MethodSignature) point.getSignature();
		Method method = ms.getMethod();
		Map<String,String[]> map = request.getParameterMap();
		Validator validator = method.getAnnotation(Validator.class);
		if(validator != null){
			String[] formats = validator.format();
			String[] names = validator.name();
			AjaxResult res = checkParamMain(names,formats,map);
			if(!res.beSuccess())
				return res;
		}
		return point.proceed();
	}

	/**
	 * 验证参数主方法
	 *
	 * @param formats
	 * @param params
	 * @throws Exception
	 */
	private AjaxResult checkParamMain(String[] names, String[] formats, Map<String,String[]> params) throws Exception {
		AjaxResult res = new AjaxResult();
		if (names.length == formats.length) {
			for (int i = 0; i < formats.length; i++) {
				String format = formats[i];
				String name = names[i];
				String value = params.get(name) == null ? null : params.get(name)[0];
				if(StrKit.isEmpty(value)) {
					res.addError(name + " is not null");
					break;
				}

				if (format.contains("len")) {
					// 检查参数长度是否对应
					if (!checkLength(format, value, name, res))
						break;
				} else if (!format.equals(Format.NOT_NULL)) {
					// 根据正则检查参数是否正确
					if (!checkReg(format, value, name, res))
						break;
				}
			}
		} else {
			throw new Exception("验证的参数与格式的长度不一致");
		}
		return res;
	}


	/**
	 * 根据长度检查参数是否正确
	 *
	 * @param format
	 * @param value
	 * @return
	 * @throws Exception
	 */
	private boolean checkLength(String name, String format, String value, AjaxResult res) throws Exception {
		String[] nums = format.split("_");
		boolean lenFlag = true;
		if (nums.length == 3) {
			if (nums[1].equals("min")) {
				if (value.length() > Integer.valueOf(nums[2])) {
					lenFlag = false;
				}
			} else if (nums[2].equals("max")) {
				if (value.length() < Integer.valueOf(nums[1])) {
					lenFlag = false;
				}
			} else {
				if (value.length() > Integer.valueOf(nums[2]) || value.length() < Integer.valueOf(nums[1])) {
					lenFlag = false;
				}
			}
		} else if (nums.length == 2) {
			if (value.length() != Integer.valueOf(nums[1])) {
				lenFlag = false;
			}
		} else {
			throw new Exception("长度验证的参数格式不正确");
		}

		if (!lenFlag) {
			res.addError(name + "-length not correct");
			return false;
		}
		return true;
	}

	/**
	 * 根据正则检查参数是否正确
	 *
	 * @param format
	 * @param value
	 * @param name
	 * @return
	 */
	private boolean checkReg(String format, String value, String name, AjaxResult res) {
		Pattern pattern = Pattern.compile(format, Pattern.CASE_INSENSITIVE);
		Matcher matcher = pattern.matcher(value);
		if (!matcher.matches()) {
			res.addError(name + "-parameter format error");
			return false;
		}
		return true;
	}
}
